﻿Imports System
Imports System.CodeDom
Imports System.Collections.Generic
Imports System.Diagnostics.CodeAnalysis
Imports System.Globalization
Imports System.Reflection
Imports System.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend MustInherit Class Literal
        ' Methods
        Protected Sub New()
        End Sub

        Private Shared Sub AddLiftedOperators(ByVal type As Type, ByVal methodName As String, ByVal group As OperatorGrouping, ByVal arg1 As Type, ByVal arg2 As Type, ByVal candidates As List([Of] MethodInfo))
            Dim num As Integer = 0
            Dim info As MethodInfo
            For Each info In type.GetMethods((BindingFlags.Public Or BindingFlags.Static))
                Dim parameters As ParameterInfo() = info.GetParameters
                If ((info.Name = methodName) AndAlso (parameters.Length = 2)) Then
                    Dim item As MethodInfo = Literal.EvaluateLiftedMethod(info, parameters, group, arg1, arg2)
                    If (Not item Is Nothing) Then
                        num += 1
                        If Not candidates.Contains(item) Then
                            candidates.Add(item)
                        End If
                    End If
                End If
            Next
            If ((num <= 0) AndAlso (Not type Is GetType(Object))) Then
                type = type.BaseType
                If (Not type Is Nothing) Then
                    Dim info3 As MethodInfo
                    For Each info3 In type.GetMethods((BindingFlags.Public Or BindingFlags.Static))
                        Dim infoArray3 As ParameterInfo() = info3.GetParameters
                        If ((info3.Name = methodName) AndAlso (infoArray3.Length = 2)) Then
                            Dim info4 As MethodInfo = Literal.EvaluateLiftedMethod(info3, infoArray3, group, arg1, arg2)
                            If ((Not info4 Is Nothing) AndAlso Not candidates.Contains(info4)) Then
                                candidates.Add(info4)
                            End If
                        End If
                    Next
                End If
            End If
        End Sub

        Private Shared Sub AddOperatorOverloads(ByVal type As Type, ByVal methodName As String, ByVal arg1 As Type, ByVal arg2 As Type, ByVal candidates As List([Of] MethodInfo))
            Dim num As Integer = 0
            Dim info As MethodInfo
            For Each info In type.GetMethods((BindingFlags.Public Or BindingFlags.Static))
                Dim parameters As ParameterInfo() = info.GetParameters
                If (((info.Name = methodName) AndAlso (parameters.Length = 2)) AndAlso Literal.EvaluateMethod(parameters, arg1, arg2)) Then
                    num += 1
                    If Not candidates.Contains(info) Then
                        candidates.Add(info)
                    End If
                End If
            Next
            If ((num <= 0) AndAlso (Not type Is GetType(Object))) Then
                type = type.BaseType
                If (Not type Is Nothing) Then
                    Dim info2 As MethodInfo
                    For Each info2 In type.GetMethods((BindingFlags.Public Or BindingFlags.Static))
                        Dim infoArray3 As ParameterInfo() = info2.GetParameters
                        If (((info2.Name = methodName) AndAlso (infoArray3.Length = 2)) AndAlso (Literal.EvaluateMethod(infoArray3, arg1, arg2) AndAlso Not candidates.Contains(info2))) Then
                            candidates.Add(info2)
                        End If
                    Next
                End If
            End If
        End Sub

        <SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")> _
        Friend Shared Function AllowedComparison(ByVal lhs As Type, ByVal lhsExpression As CodeExpression, ByVal rhs As Type, ByVal rhsExpression As CodeExpression, ByVal comparison As CodeBinaryOperatorType, ByVal validator As RuleValidation, <Out> ByRef [error] As ValidationError) As RuleBinaryExpressionInfo
            Dim flags As TypeFlags
            Dim flags2 As TypeFlags
            If (Not Literal.supportedTypes.TryGetValue(lhs, flags) OrElse Not Literal.supportedTypes.TryGetValue(rhs, flags2)) Then
                Dim mi As MethodInfo = Literal.MapOperatorToMethod(comparison, lhs, lhsExpression, rhs, rhsExpression, validator, [error])
                If (Not mi Is Nothing) Then
                    Return New RuleBinaryExpressionInfo(lhs, rhs, mi)
                End If
                Return Nothing
            End If
            If (flags = flags2) Then
                If ((flags = TypeFlags.Bool) AndAlso (comparison <> CodeBinaryOperatorType.ValueEquality)) Then
                    Dim str As String = String.Format(CultureInfo.CurrentCulture, Messages.RelationalOpBadTypes, New Object() { comparison.ToString, RuleDecompiler.DecompileType(lhs), RuleDecompiler.DecompileType(rhs) })
                    [error] = New ValidationError(str, &H545)
                    Return Nothing
                End If
                [error] = Nothing
                Return New RuleBinaryExpressionInfo(lhs, rhs, GetType(Boolean))
            End If
            Select Case (flags Or flags2)
                Case (TypeFlags.[ULong] Or TypeFlags.UnsignedNumbers), (TypeFlags.Float Or TypeFlags.SignedNumbers), (TypeFlags.Float Or TypeFlags.UnsignedNumbers), (TypeFlags.Float Or TypeFlags.[ULong]), (TypeFlags.UnsignedNumbers Or TypeFlags.SignedNumbers), (TypeFlags.Decimal Or TypeFlags.SignedNumbers), (TypeFlags.Decimal Or TypeFlags.UnsignedNumbers), (TypeFlags.Decimal Or TypeFlags.[ULong])
                    [error] = Nothing
                    Return New RuleBinaryExpressionInfo(lhs, rhs, GetType(Boolean))
            End Select
            Dim errorText As String = String.Format(CultureInfo.CurrentCulture, Messages.RelationalOpBadTypes, New Object() { comparison.ToString, If((lhs Is GetType(NullLiteral)), Messages.NullValue, RuleDecompiler.DecompileType(lhs)), If((rhs Is GetType(NullLiteral)), Messages.NullValue, RuleDecompiler.DecompileType(rhs)) })
            [error] = New ValidationError(errorText, &H545)
            Return Nothing
        End Function

        Private Shared Function CreateMakersDictionary() As Dictionary([Of] Type, LiteralMaker)
            Dim dictionary As New Dictionary([Of] Type, LiteralMaker)(&H20)
            dictionary.Add(GetType(Byte), New LiteralMaker(AddressOf Literal.MakeByte))
            dictionary.Add(GetType([SByte]), New LiteralMaker(AddressOf Literal.MakeSByte))
            dictionary.Add(GetType(Short), New LiteralMaker(AddressOf Literal.MakeShort))
            dictionary.Add(GetType(Integer), New LiteralMaker(AddressOf Literal.MakeInt))
            dictionary.Add(GetType(Long), New LiteralMaker(AddressOf Literal.MakeLong))
            dictionary.Add(GetType(UInt16), New LiteralMaker(AddressOf Literal.MakeUShort))
            dictionary.Add(GetType(UInt32), New LiteralMaker(AddressOf Literal.MakeUInt))
            dictionary.Add(GetType(UInt64), New LiteralMaker(AddressOf Literal.MakeULong))
            dictionary.Add(GetType(Single), New LiteralMaker(AddressOf Literal.MakeFloat))
            dictionary.Add(GetType(Double), New LiteralMaker(AddressOf Literal.MakeDouble))
            dictionary.Add(GetType(Char), New LiteralMaker(AddressOf Literal.MakeChar))
            dictionary.Add(GetType(String), New LiteralMaker(AddressOf Literal.MakeString))
            dictionary.Add(GetType(Decimal), New LiteralMaker(AddressOf Literal.MakeDecimal))
            dictionary.Add(GetType(Boolean), New LiteralMaker(AddressOf Literal.MakeBool))
            dictionary.Add(GetType(Nullable([Of] Byte)), New LiteralMaker(AddressOf Literal.MakeByte))
            dictionary.Add(GetType(Nullable([Of] [SByte])), New LiteralMaker(AddressOf Literal.MakeSByte))
            dictionary.Add(GetType(Nullable([Of] Short)), New LiteralMaker(AddressOf Literal.MakeShort))
            dictionary.Add(GetType(Nullable([Of] Integer)), New LiteralMaker(AddressOf Literal.MakeInt))
            dictionary.Add(GetType(Nullable([Of] Long)), New LiteralMaker(AddressOf Literal.MakeLong))
            dictionary.Add(GetType(Nullable([Of] UInt16)), New LiteralMaker(AddressOf Literal.MakeUShort))
            dictionary.Add(GetType(Nullable([Of] UInt32)), New LiteralMaker(AddressOf Literal.MakeUInt))
            dictionary.Add(GetType(Nullable([Of] UInt64)), New LiteralMaker(AddressOf Literal.MakeULong))
            dictionary.Add(GetType(Nullable([Of] Single)), New LiteralMaker(AddressOf Literal.MakeFloat))
            dictionary.Add(GetType(Nullable([Of] Double)), New LiteralMaker(AddressOf Literal.MakeDouble))
            dictionary.Add(GetType(Nullable([Of] Char)), New LiteralMaker(AddressOf Literal.MakeChar))
            dictionary.Add(GetType(Nullable([Of] Decimal)), New LiteralMaker(AddressOf Literal.MakeDecimal))
            dictionary.Add(GetType(Nullable([Of] Boolean)), New LiteralMaker(AddressOf Literal.MakeBool))
            Return dictionary
        End Function

        Private Shared Function CreateTypesDictionary() As Dictionary([Of] Type, TypeFlags)
            Dim dictionary As New Dictionary([Of] Type, TypeFlags)(&H20)
            dictionary.Add(GetType(Byte), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(Nullable([Of] Byte)), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType([SByte]), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Nullable([Of] [SByte])), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Short), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Nullable([Of] Short)), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Integer), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Nullable([Of] Integer)), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Long), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(Nullable([Of] Long)), TypeFlags.SignedNumbers)
            dictionary.Add(GetType(UInt16), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(Nullable([Of] UInt16)), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(UInt32), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(Nullable([Of] UInt32)), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(UInt64), TypeFlags.[ULong])
            dictionary.Add(GetType(Nullable([Of] UInt64)), TypeFlags.[ULong])
            dictionary.Add(GetType(Single), TypeFlags.Float)
            dictionary.Add(GetType(Nullable([Of] Single)), TypeFlags.Float)
            dictionary.Add(GetType(Double), TypeFlags.Float)
            dictionary.Add(GetType(Nullable([Of] Double)), TypeFlags.Float)
            dictionary.Add(GetType(Char), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(Nullable([Of] Char)), TypeFlags.UnsignedNumbers)
            dictionary.Add(GetType(String), TypeFlags.String)
            dictionary.Add(GetType(Decimal), TypeFlags.Decimal)
            dictionary.Add(GetType(Nullable([Of] Decimal)), TypeFlags.Decimal)
            dictionary.Add(GetType(Boolean), TypeFlags.Bool)
            dictionary.Add(GetType(Nullable([Of] Boolean)), TypeFlags.Bool)
            Return dictionary
        End Function

        Private Shared Function DecimalIntegerLiteralZero(ByVal type As Type, ByVal expression As CodePrimitiveExpression) As Boolean
            If (Not expression Is Nothing) Then
                If (type Is GetType(Integer)) Then
                    Return expression.Value.Equals(0)
                End If
                If (type Is GetType(UInt32)) Then
                    Return expression.Value.Equals(0)
                End If
                If (type Is GetType(Long)) Then
                    Return expression.Value.Equals(0)
                End If
                If (type Is GetType(UInt64)) Then
                    Return expression.Value.Equals([CULng](0))
                End If
            End If
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Boolean) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Byte) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Char) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Decimal) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Double) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Short) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Integer) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Long) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As [SByte]) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As Single) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As String) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As UInt16) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As UInt32) As Boolean
            Return False
        End Function

        Friend Overridable Function Equal(ByVal literalValue As UInt64) As Boolean
            Return False
        End Function

        Friend MustOverride Function Equal(ByVal rhs As Literal) As Boolean

        Private Shared Function EvaluateLiftedMethod(ByVal mi As MethodInfo, ByVal parameters As ParameterInfo(), ByVal group As OperatorGrouping, ByVal arg1 As Type, ByVal arg2 As Type) As MethodInfo
            Dim parameterType As Type = parameters(0).ParameterType
            Dim type As Type = parameters(1).ParameterType
            If (ConditionHelper.IsNonNullableValueType(parameterType) AndAlso ConditionHelper.IsNonNullableValueType(type)) Then
                parameterType = GetType(Nullable([Of] )).MakeGenericType(New Type() { parameterType })
                type = GetType(Nullable([Of] )).MakeGenericType(New Type() { type })
                Select Case group
                    Case OperatorGrouping.Arithmetic
                        If ((Not ConditionHelper.IsNonNullableValueType(mi.ReturnType) OrElse Not RuleValidation.ImplicitConversion(arg1, parameterType)) OrElse Not RuleValidation.ImplicitConversion(arg2, type)) Then
                            Exit Select
                        End If
                        Return New LiftedArithmeticOperatorMethodInfo(mi)
                    Case OperatorGrouping.Equality
                        If (((Not mi.ReturnType Is GetType(Boolean)) OrElse Not RuleValidation.ImplicitConversion(arg1, parameterType)) OrElse Not RuleValidation.ImplicitConversion(arg2, type)) Then
                            Exit Select
                        End If
                        Return New LiftedEqualityOperatorMethodInfo(mi)
                    Case OperatorGrouping.Relational
                        If (((Not mi.ReturnType Is GetType(Boolean)) OrElse Not RuleValidation.ImplicitConversion(arg1, parameterType)) OrElse Not RuleValidation.ImplicitConversion(arg2, type)) Then
                            Exit Select
                        End If
                        Return New LiftedRelationalOperatorMethodInfo(mi)
                End Select
            End If
            Return Nothing
        End Function

        Private Shared Function EvaluateMethod(ByVal parameters As ParameterInfo(), ByVal arg1 As Type, ByVal arg2 As Type) As Boolean
            Dim parameterType As Type = parameters(0).ParameterType
            Dim toType As Type = parameters(1).ParameterType
            Return (RuleValidation.ImplicitConversion(arg1, parameterType) AndAlso RuleValidation.ImplicitConversion(arg2, toType))
        End Function

        Friend Overridable Function GreaterThan() As Boolean
            Return False
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Boolean) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Byte) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Char) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Decimal) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Double) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Short) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Integer) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Long) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As [SByte]) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As Single) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As String) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As UInt16) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As UInt32) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend Overridable Function GreaterThan(ByVal literalValue As UInt64) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThan, Me.m_type)
        End Function

        Friend MustOverride Function GreaterThan(ByVal rhs As Literal) As Boolean

        Friend Overridable Function GreaterThanOrEqual() As Boolean
            Return False
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Boolean) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Byte) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Char) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Decimal) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Double) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Short) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Integer) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Long) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As [SByte]) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As Single) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As String) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As UInt16) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As UInt32) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function GreaterThanOrEqual(ByVal literalValue As UInt64) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.GreaterThanOrEqual, Me.m_type)
        End Function

        Friend MustOverride Function GreaterThanOrEqual(ByVal rhs As Literal) As Boolean

        Friend Overridable Function LessThan() As Boolean
            Return False
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Boolean) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Byte) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Char) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Decimal) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Double) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Short) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Integer) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Long) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As [SByte]) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As Single) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As String) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As UInt16) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As UInt32) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend Overridable Function LessThan(ByVal literalValue As UInt64) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThan, Me.m_type)
        End Function

        Friend MustOverride Function LessThan(ByVal rhs As Literal) As Boolean

        Friend Overridable Function LessThanOrEqual() As Boolean
            Return False
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Boolean) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Byte) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Char) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Decimal) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Double) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Short) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Integer) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Long) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As [SByte]) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As Single) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As String) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As UInt16) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As UInt32) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend Overridable Function LessThanOrEqual(ByVal literalValue As UInt64) As Boolean
            Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.IncompatibleComparisonTypes, New Object() { literalValue.GetType, Me.m_type }), literalValue.GetType, CodeBinaryOperatorType.LessThanOrEqual, Me.m_type)
        End Function

        Friend MustOverride Function LessThanOrEqual(ByVal rhs As Literal) As Boolean

        Private Shared Function MakeBool(ByVal literalValue As Object) As Literal
            Return New BoolLiteral(CBool(literalValue))
        End Function

        Private Shared Function MakeByte(ByVal literalValue As Object) As Literal
            Return New ByteLiteral(CByte(literalValue))
        End Function

        Private Shared Function MakeChar(ByVal literalValue As Object) As Literal
            Return New CharLiteral(DirectCast(literalValue, Char))
        End Function

        Private Shared Function MakeDecimal(ByVal literalValue As Object) As Literal
            Return New DecimalLiteral(CDec(literalValue))
        End Function

        Private Shared Function MakeDouble(ByVal literalValue As Object) As Literal
            Return New DoubleLiteral(CDbl(literalValue))
        End Function

        Private Shared Function MakeFloat(ByVal literalValue As Object) As Literal
            Return New FloatLiteral(CSng(literalValue))
        End Function

        Private Shared Function MakeInt(ByVal literalValue As Object) As Literal
            Return New IntLiteral(CInt(literalValue))
        End Function

        Friend Shared Function MakeLiteral(ByVal literalType As Type, ByVal literalValue As Object) As Literal
            Dim maker As LiteralMaker
            If (literalValue Is Nothing) Then
                Return New NullLiteral(literalType)
            End If
            If Literal.types.TryGetValue(literalType, maker) Then
                Try 
                    Return maker.Invoke(literalValue)
                Catch exception As InvalidCastException
                    Throw New RuleEvaluationIncompatibleTypesException(String.Format(CultureInfo.CurrentCulture, Messages.InvalidCast, New Object() { RuleDecompiler.DecompileType(literalValue.GetType), RuleDecompiler.DecompileType(literalType) }), literalType, CodeBinaryOperatorType.Assign, literalValue.GetType, exception)
                End Try
            End If
            Return Nothing
        End Function

        Private Shared Function MakeLong(ByVal literalValue As Object) As Literal
            Return New LongLiteral(CLng(literalValue))
        End Function

        Private Shared Function MakeSByte(ByVal literalValue As Object) As Literal
            Return New SByteLiteral([CSByte](literalValue))
        End Function

        Private Shared Function MakeShort(ByVal literalValue As Object) As Literal
            Return New ShortLiteral(CShort(literalValue))
        End Function

        Private Shared Function MakeString(ByVal literalValue As Object) As Literal
            Return New StringLiteral(CStr(literalValue))
        End Function

        Private Shared Function MakeUInt(ByVal literalValue As Object) As Literal
            Return New UIntLiteral(DirectCast(literalValue, UInt32))
        End Function

        Private Shared Function MakeULong(ByVal literalValue As Object) As Literal
            Return New ULongLiteral([CULng](literalValue))
        End Function

        Private Shared Function MakeUShort(ByVal literalValue As Object) As Literal
            Return New UShortLiteral([CUShort](literalValue))
        End Function

        <SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity"), SuppressMessage("Microsoft.Performance", "CA1803:AvoidCostlyCallsWherePossible"), SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")> _
        Friend Shared Function MapOperatorToMethod(ByVal op As CodeBinaryOperatorType, ByVal lhs As Type, ByVal lhsExpression As CodeExpression, ByVal rhs As Type, ByVal rhsExpression As CodeExpression, ByVal validator As RuleValidation, <Out> ByRef [error] As ValidationError) As MethodInfo
            Dim str As String
            Dim str2 As String
            Dim arithmetic As OperatorGrouping
            Select Case op
                Case CodeBinaryOperatorType.Add
                    str = "op_Addition"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.Subtract
                    str = "op_Subtraction"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.Multiply
                    str = "op_Multiply"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.Divide
                    str = "op_Division"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.Modulus
                    str = "op_Modulus"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.ValueEquality
                    str = "op_Equality"
                    arithmetic = OperatorGrouping.Equality
                    Exit Select
                Case CodeBinaryOperatorType.BitwiseOr
                    str = "op_BitwiseOr"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.BitwiseAnd
                    str = "op_BitwiseAnd"
                    arithmetic = OperatorGrouping.Arithmetic
                    Exit Select
                Case CodeBinaryOperatorType.LessThan
                    str = "op_LessThan"
                    arithmetic = OperatorGrouping.Relational
                    Exit Select
                Case CodeBinaryOperatorType.LessThanOrEqual
                    str = "op_LessThanOrEqual"
                    arithmetic = OperatorGrouping.Relational
                    Exit Select
                Case CodeBinaryOperatorType.GreaterThan
                    str = "op_GreaterThan"
                    arithmetic = OperatorGrouping.Relational
                    Exit Select
                Case CodeBinaryOperatorType.GreaterThanOrEqual
                    str = "op_GreaterThanOrEqual"
                    arithmetic = OperatorGrouping.Relational
                    Exit Select
                Case Else
                    str2 = String.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, New Object() { op.ToString })
                    [error] = New ValidationError(str2, &H548)
                    Return Nothing
            End Select
            Dim candidates As New List([Of] MethodInfo)
            Dim flag As Boolean = ConditionHelper.IsNullableValueType(lhs)
            Dim flag2 As Boolean = ConditionHelper.IsNullableValueType(rhs)
            Dim rhsType As Type = If(flag, Nullable.GetUnderlyingType(lhs), lhs)
            Dim type As Type = If(flag2, Nullable.GetUnderlyingType(rhs), rhs)
            If Not rhsType.IsEnum Then
                If type.IsEnum Then
                    Dim underlyingType As Type
                    Select Case op
                        Case CodeBinaryOperatorType.Add
                            underlyingType = EnumHelper.GetUnderlyingType(type)
                            If ((underlyingType Is Nothing) OrElse Not RuleValidation.TypesAreAssignable(rhsType, underlyingType, lhsExpression, [error])) Then
                                goto Label_037B
                            End If
                            [error] = Nothing
                            Return New EnumOperationMethodInfo(lhs, op, rhs, False)
                        Case CodeBinaryOperatorType.Subtract
                            underlyingType = EnumHelper.GetUnderlyingType(type)
                            If (underlyingType Is Nothing) Then
                                goto Label_037B
                            End If
                            Dim expression As CodePrimitiveExpression = [TryCast](lhsExpression,CodePrimitiveExpression)
                            If Not Literal.DecimalIntegerLiteralZero(lhs, expression) Then
                                If RuleValidation.TypesAreAssignable(rhsType, underlyingType, lhsExpression, [error]) Then
                                    [error] = Nothing
                                    Return New EnumOperationMethodInfo(lhs, op, rhs, False)
                                End If
                                goto Label_037B
                            End If
                            [error] = Nothing
                            Return New EnumOperationMethodInfo(lhs, op, rhs, True)
                        Case CodeBinaryOperatorType.ValueEquality, CodeBinaryOperatorType.LessThan, CodeBinaryOperatorType.LessThanOrEqual, CodeBinaryOperatorType.GreaterThan, CodeBinaryOperatorType.GreaterThanOrEqual
                            If (Not flag2 OrElse (Not lhs Is GetType(NullLiteral))) Then
                                If Literal.DecimalIntegerLiteralZero(lhs, [TryCast](lhsExpression,CodePrimitiveExpression)) Then
                                    [error] = Nothing
                                    Return New EnumOperationMethodInfo(lhs, op, rhs, True)
                                End If
                                goto Label_037B
                            End If
                            [error] = Nothing
                            Return New EnumOperationMethodInfo(rhs, op, rhs, False)
                        Case CodeBinaryOperatorType.BitwiseOr, CodeBinaryOperatorType.BitwiseAnd, CodeBinaryOperatorType.BooleanOr, CodeBinaryOperatorType.BooleanAnd
                            goto Label_037B
                    End Select
                End If
            Else
                Dim type3 As Type
                Select Case op
                    Case CodeBinaryOperatorType.Add
                        type3 = EnumHelper.GetUnderlyingType(rhsType)
                        If ((type3 Is Nothing) OrElse Not RuleValidation.TypesAreAssignable(type, type3, rhsExpression, [error])) Then
                            goto Label_037B
                        End If
                        [error] = Nothing
                        Return New EnumOperationMethodInfo(lhs, op, rhs, False)
                    Case CodeBinaryOperatorType.Subtract
                        type3 = EnumHelper.GetUnderlyingType(rhsType)
                        If (type3 Is Nothing) Then
                            goto Label_037B
                        End If
                        If (Not rhsType Is type) Then
                            If Literal.DecimalIntegerLiteralZero(rhs, [TryCast](rhsExpression,CodePrimitiveExpression)) Then
                                [error] = Nothing
                                Return New EnumOperationMethodInfo(lhs, op, rhs, True)
                            End If
                            If RuleValidation.TypesAreAssignable(type, type3, rhsExpression, [error]) Then
                                [error] = Nothing
                                Return New EnumOperationMethodInfo(lhs, op, rhs, False)
                            End If
                            goto Label_037B
                        End If
                        [error] = Nothing
                        Return New EnumOperationMethodInfo(lhs, op, rhs, False)
                    Case CodeBinaryOperatorType.ValueEquality, CodeBinaryOperatorType.LessThan, CodeBinaryOperatorType.LessThanOrEqual, CodeBinaryOperatorType.GreaterThan, CodeBinaryOperatorType.GreaterThanOrEqual
                        If (Not rhsType Is type) Then
                            If (flag AndAlso (rhs Is GetType(NullLiteral))) Then
                                [error] = Nothing
                                Return New EnumOperationMethodInfo(lhs, op, lhs, False)
                            End If
                            If Literal.DecimalIntegerLiteralZero(rhs, [TryCast](rhsExpression,CodePrimitiveExpression)) Then
                                [error] = Nothing
                                Return New EnumOperationMethodInfo(lhs, op, rhs, True)
                            End If
                            goto Label_037B
                        End If
                        [error] = Nothing
                        Return New EnumOperationMethodInfo(lhs, op, rhs, False)
                    Case CodeBinaryOperatorType.BitwiseOr, CodeBinaryOperatorType.BitwiseAnd, CodeBinaryOperatorType.BooleanOr, CodeBinaryOperatorType.BooleanAnd
                        goto Label_037B
                End Select
            End If
        Label_037B:
            Literal.AddOperatorOverloads(rhsType, str, lhs, rhs, candidates)
            Literal.AddOperatorOverloads(type, str, lhs, rhs, candidates)
            If ((flag OrElse flag2) OrElse ((lhs Is GetType(NullLiteral)) OrElse (rhs Is GetType(NullLiteral)))) Then
                Literal.AddLiftedOperators(rhsType, str, arithmetic, rhsType, type, candidates)
                Literal.AddLiftedOperators(type, str, arithmetic, rhsType, type, candidates)
            End If
            If (candidates.Count = 0) Then
                str = str.Substring(3)
                Dim info As MethodInfo
                For Each info In GetType(DefaultOperators).GetMethods
                    If (info.Name = str) Then
                        Dim parameters As ParameterInfo() = info.GetParameters
                        Dim parameterType As Type = parameters(0).ParameterType
                        Dim toType As Type = parameters(1).ParameterType
                        If (RuleValidation.ImplicitConversion(lhs, parameterType) AndAlso RuleValidation.ImplicitConversion(rhs, toType)) Then
                            candidates.Add(info)
                        End If
                    End If
                Next
                If ((((candidates.Count = 0) AndAlso ("Equality" = str)) AndAlso (Not lhs.IsValueType AndAlso Not rhs.IsValueType)) AndAlso (((lhs Is GetType(NullLiteral)) OrElse (rhs Is GetType(NullLiteral))) OrElse (lhs.IsAssignableFrom(rhs) OrElse rhs.IsAssignableFrom(lhs)))) Then
                    candidates.Add(Literal.ObjectEquality)
                End If
                If ((candidates.Count = 0) AndAlso ((flag OrElse flag2) OrElse ((lhs Is GetType(NullLiteral)) OrElse (rhs Is GetType(NullLiteral))))) Then
                    Dim info2 As MethodInfo
                    For Each info2 In GetType(DefaultOperators).GetMethods
                        If (info2.Name = str) Then
                            Dim infoArray2 As ParameterInfo() = info2.GetParameters
                            Dim item As MethodInfo = Literal.EvaluateLiftedMethod(info2, infoArray2, arithmetic, rhsType, type)
                            If (Not item Is Nothing) Then
                                candidates.Add(item)
                            End If
                        End If
                    Next
                End If
            End If
            If (candidates.Count = 1) Then
                [error] = Nothing
                Return candidates.Item(0)
            End If
            If (candidates.Count = 0) Then
                str2 = String.Format(CultureInfo.CurrentCulture, If((arithmetic = OperatorGrouping.Arithmetic), Messages.ArithOpBadTypes, Messages.RelationalOpBadTypes), New Object() { op.ToString, If((lhs Is GetType(NullLiteral)), Messages.NullValue, RuleDecompiler.DecompileType(lhs)), If((rhs Is GetType(NullLiteral)), Messages.NullValue, RuleDecompiler.DecompileType(rhs)) })
                [error] = New ValidationError(str2, &H545)
                Return Nothing
            End If
            Dim info4 As MethodInfo = validator.FindBestCandidate(Nothing, candidates, New Type() { lhs, rhs })
            If (Not info4 Is Nothing) Then
                [error] = Nothing
                Return info4
            End If
            str2 = String.Format(CultureInfo.CurrentCulture, Messages.AmbiguousOperator, New Object() { op.ToString, RuleDecompiler.DecompileMethod(candidates.Item(0)), RuleDecompiler.DecompileMethod(candidates.Item(1)) })
            [error] = New ValidationError(str2, &H545)
            Return Nothing
        End Function


        ' Properties
        Friend MustOverride ReadOnly Property Value As Object


        ' Fields
        Protected Friend m_type As Type
        Friend Shared ObjectEquality As MethodInfo = GetType(DefaultOperators).GetMethod("ObjectEquality")
        Private Shared supportedTypes As Dictionary([Of] Type, TypeFlags) = Literal.CreateTypesDictionary
        Private Shared types As Dictionary([Of] Type, LiteralMaker) = Literal.CreateMakersDictionary

        ' Nested Types
        Friend Class DefaultOperators
            ' Methods
            Public Shared Function Addition(ByVal x As Decimal, ByVal y As Decimal) As Decimal
                Return (x + y)
            End Function

            Public Shared Function Addition(ByVal x As Double, ByVal y As Double) As Double
                Return (x + y)
            End Function

            Public Shared Function Addition(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x + y)
            End Function

            Public Shared Function Addition(ByVal x As Long, ByVal y As Long) As Long
                Return (x + y)
            End Function

            Public Shared Function Addition(ByVal x As Object, ByVal y As String) As String
                Return (x & y)
            End Function

            Public Shared Function Addition(ByVal x As Single, ByVal y As Single) As Single
                Return (x + y)
            End Function

            Public Shared Function Addition(ByVal x As String, ByVal y As Object) As String
                Return (x & y)
            End Function

            Public Shared Function Addition(ByVal x As String, ByVal y As String) As String
                Return (x & y)
            End Function

            Public Shared Function Addition(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x + y)
            End Function

            Public Shared Function Addition(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x + y)
            End Function

            Public Shared Function BitwiseAnd(ByVal x As Boolean, ByVal y As Boolean) As Boolean
                Return (x And y)
            End Function

            Public Shared Function BitwiseAnd(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x And y)
            End Function

            Public Shared Function BitwiseAnd(ByVal x As Long, ByVal y As Long) As Long
                Return (x And y)
            End Function

            Public Shared Function BitwiseAnd(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x And y)
            End Function

            Public Shared Function BitwiseAnd(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x And y)
            End Function

            Public Shared Function BitwiseOr(ByVal x As Boolean, ByVal y As Boolean) As Boolean
                Return (x Or y)
            End Function

            Public Shared Function BitwiseOr(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x Or y)
            End Function

            Public Shared Function BitwiseOr(ByVal x As Long, ByVal y As Long) As Long
                Return (x Or y)
            End Function

            Public Shared Function BitwiseOr(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x Or y)
            End Function

            Public Shared Function BitwiseOr(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x Or y)
            End Function

            Public Shared Function Division(ByVal x As Decimal, ByVal y As Decimal) As Decimal
                Return (x / y)
            End Function

            Public Shared Function Division(ByVal x As Double, ByVal y As Double) As Double
                Return (x / y)
            End Function

            Public Shared Function Division(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x / y)
            End Function

            Public Shared Function Division(ByVal x As Long, ByVal y As Long) As Long
                Return (x / y)
            End Function

            Public Shared Function Division(ByVal x As Single, ByVal y As Single) As Single
                Return (x / y)
            End Function

            Public Shared Function Division(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x / y)
            End Function

            Public Shared Function Division(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x / y)
            End Function

            Public Shared Function Equality(ByVal x As Boolean, ByVal y As Boolean) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As Decimal, ByVal y As Decimal) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As Double, ByVal y As Double) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As Integer, ByVal y As Integer) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As Long, ByVal y As Long) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As Single, ByVal y As Single) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As String, ByVal y As String) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As UInt32, ByVal y As UInt32) As Boolean
                Return (x = y)
            End Function

            Public Shared Function Equality(ByVal x As UInt64, ByVal y As UInt64) As Boolean
                Return (x = y)
            End Function

            Public Shared Function GreaterThan(ByVal x As Decimal, ByVal y As Decimal) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThan(ByVal x As Double, ByVal y As Double) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThan(ByVal x As Integer, ByVal y As Integer) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThan(ByVal x As Long, ByVal y As Long) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThan(ByVal x As Single, ByVal y As Single) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThan(ByVal x As UInt32, ByVal y As UInt32) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThan(ByVal x As UInt64, ByVal y As UInt64) As Boolean
                Return (x > y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As Decimal, ByVal y As Decimal) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As Double, ByVal y As Double) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As Integer, ByVal y As Integer) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As Long, ByVal y As Long) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As Single, ByVal y As Single) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As UInt32, ByVal y As UInt32) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function GreaterThanOrEqual(ByVal x As UInt64, ByVal y As UInt64) As Boolean
                Return (x >= y)
            End Function

            Public Shared Function LessThan(ByVal x As Decimal, ByVal y As Decimal) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThan(ByVal x As Double, ByVal y As Double) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThan(ByVal x As Integer, ByVal y As Integer) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThan(ByVal x As Long, ByVal y As Long) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThan(ByVal x As Single, ByVal y As Single) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThan(ByVal x As UInt32, ByVal y As UInt32) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThan(ByVal x As UInt64, ByVal y As UInt64) As Boolean
                Return (x < y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As Decimal, ByVal y As Decimal) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As Double, ByVal y As Double) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As Integer, ByVal y As Integer) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As Long, ByVal y As Long) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As Single, ByVal y As Single) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As UInt32, ByVal y As UInt32) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function LessThanOrEqual(ByVal x As UInt64, ByVal y As UInt64) As Boolean
                Return (x <= y)
            End Function

            Public Shared Function Modulus(ByVal x As Decimal, ByVal y As Decimal) As Decimal
                Return Decimal.op_Modulus(x, y)
            End Function

            Public Shared Function Modulus(ByVal x As Double, ByVal y As Double) As Double
                Return (x Mod y)
            End Function

            Public Shared Function Modulus(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x Mod y)
            End Function

            Public Shared Function Modulus(ByVal x As Long, ByVal y As Long) As Long
                Return (x Mod y)
            End Function

            Public Shared Function Modulus(ByVal x As Single, ByVal y As Single) As Single
                Return (x Mod y)
            End Function

            Public Shared Function Modulus(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x Mod y)
            End Function

            Public Shared Function Modulus(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x Mod y)
            End Function

            Public Shared Function Multiply(ByVal x As Decimal, ByVal y As Decimal) As Decimal
                Return (x * y)
            End Function

            Public Shared Function Multiply(ByVal x As Double, ByVal y As Double) As Double
                Return (x * y)
            End Function

            Public Shared Function Multiply(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x * y)
            End Function

            Public Shared Function Multiply(ByVal x As Long, ByVal y As Long) As Long
                Return (x * y)
            End Function

            Public Shared Function Multiply(ByVal x As Single, ByVal y As Single) As Single
                Return (x * y)
            End Function

            Public Shared Function Multiply(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x * y)
            End Function

            Public Shared Function Multiply(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x * y)
            End Function

            Public Shared Function ObjectEquality(ByVal x As Object, ByVal y As Object) As Boolean
                Return (x Is y)
            End Function

            Public Shared Function Subtraction(ByVal x As Decimal, ByVal y As Decimal) As Decimal
                Return (x - y)
            End Function

            Public Shared Function Subtraction(ByVal x As Double, ByVal y As Double) As Double
                Return (x - y)
            End Function

            Public Shared Function Subtraction(ByVal x As Integer, ByVal y As Integer) As Integer
                Return (x - y)
            End Function

            Public Shared Function Subtraction(ByVal x As Long, ByVal y As Long) As Long
                Return (x - y)
            End Function

            Public Shared Function Subtraction(ByVal x As Single, ByVal y As Single) As Single
                Return (x - y)
            End Function

            Public Shared Function Subtraction(ByVal x As UInt32, ByVal y As UInt32) As UInt32
                Return (x - y)
            End Function

            Public Shared Function Subtraction(ByVal x As UInt64, ByVal y As UInt64) As UInt64
                Return (x - y)
            End Function

        End Class

        Private Delegate Function LiteralMaker(ByVal literalValue As Object) As Literal

        Friend Enum OperatorGrouping
            ' Fields
            Arithmetic = 0
            Equality = 1
            Relational = 2
        End Enum

        <Flags> _
        Private Enum TypeFlags
            ' Fields
            Bool = &H40
            [Decimal] = &H10
            Float = 8
            SignedNumbers = 1
            [String] = &H20
            [ULong] = 4
            UnsignedNumbers = 2
        End Enum
    End Class
End Namespace

